package org.example.day11;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 4.1.8.1 实现生产者/消费者 多对对交替打印
 *      ①出现假死情况
 *          原因: 线程A调用signal有可能唤醒的还是执行set方法的线程.(当最后一个存活的线程唤醒了和自己执行一样方法的线程，就会出现假死)
 */
public class MyThread2 {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private boolean hasValue = false;
    public void set(){
        try {
            lock.lock();
            while(hasValue == true){
                System.out.println("有可能★★连续");
                condition.await();
            }
            System.out.println("打印★");
            hasValue = true;
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void get(){
        try {
            lock.lock();
            while(hasValue == false){
                System.out.println("有可能☆☆连续");
                condition.await();
            }
            System.out.println("打印☆");
            hasValue = false;
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        MyThread2 m2 = new MyThread2();
        Thread2A[] tas = new Thread2A[10];
        Thread2B[] tbs = new Thread2B[10];
        for (int i = 0; i < 10; i++) {
            tas[i] = new Thread2A(m2);
            tbs[i] = new Thread2B(m2);
            tas[i].start();
            tbs[i].start();
        }
    }
}

class Thread2A extends Thread{
    private MyThread2 m2;

    public Thread2A(MyThread2 m2) {
        this.m2 = m2;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            m2.set();
        }
    }
}

class Thread2B extends Thread{
    private MyThread2 m2;

    public Thread2B(MyThread2 m2) {
        this.m2 = m2;
    }

    @Override
    public void run() {
        for (int i = 0; i <10000; i++) {
            m2.get();
        }
    }
}

